import { Pass, FullScreenQuad } from './Pass.js';
import { CustomBlending, OneFactor, OneMinusSrcAlphaFactor, ZeroFactor, NearestFilter, FloatType, ShaderMaterial, Texture, WebGLMultipleRenderTargets } from 'three';
import { CopyShader } from '../shaders/CopyShader.js';


const frag = /* glsl */ `

uniform sampler2D tDiffuse;
uniform sampler2D accumAlpha;

varying vec2 vUv;

void main() {

	gl_FragColor = texture2D( tDiffuse, vUv );
	float a = 1. - gl_FragColor.a ;
	gl_FragColor.a  = texture2D(accumAlpha , vUv).r;
	gl_FragColor = vec4(a* gl_FragColor.rgb/ clamp(gl_FragColor.a, .001,50000.), a) ;


}
`;






class WeightedBlend extends Pass {

	constructor( { renderer, scene, camera } ) {

		super();

		this.scene = scene;
		this.camera = camera;
		this.renderer = renderer;


		const gl = renderer.getContext();

		const renderTargets = new WebGLMultipleRenderTargets( window.innerWidth *window.devicePixelRatio, window.innerHeight*window.devicePixelRatio, 2 );
		for ( let i = 0; i < renderTargets.texture.length; i ++ ) {

			renderTargets.texture[ i ].minFilter = NearestFilter;
			renderTargets.texture[ i ].magFilter = NearestFilter;
			renderTargets.texture[ i ].type = FloatType;

		}


		this.quad = new FullScreenQuad( new ShaderMaterial( {
			...CopyShader,
			transparent: true,
			fragmentShader: frag,
			uniforms: {
				tDiffuse: { value: renderTargets.texture[ 0 ] },
				accumAlpha: { value: renderTargets.texture[ 1 ] }
			},
			blending: CustomBlending,
			blendSrc: OneFactor,
			blendDst: OneMinusSrcAlphaFactor,
		} ) );
		// 可以不写
		renderTargets.texture[ 0 ].name = 'gl_FragColor';
		renderTargets.texture[ 1 ].name = 'accumAlpha';

		this.renderTargets = renderTargets;
		/*
		const textures = [ new Texture(), new Texture() ];
		const accumBuffer = gl.createFramebuffer();// 帧缓冲区唯一
		const accumTarget = gl.createTexture(); //暂时的 0  后面和 layout out accumColor 绑定
		const accumAlphaTarget = gl.createTexture(); // 暂时的 0 这个缓冲区绑定的输出只有一位 alpha   后面和 layout out accumAlpha 绑定
		textures[ 0 ].__webglTexture = accumTarget;
		textures[ 1 ].__webglTexture = accumAlphaTarget;

		this.frameBuffer = accumBuffer;
		this.textures = textures;
		gl.bindFramebuffer( gl.FRAMEBUFFER, accumBuffer );
		gl.activeTexture( gl.TEXTURE0 );

		gl.bindTexture( gl.TEXTURE_2D, accumTarget );
		gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, false );
		gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
		gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
		gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE );
		gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE );
		gl.texStorage2D( gl.TEXTURE_2D, 1, gl.RGBA16F, gl.drawingBufferWidth, gl.drawingBufferHeight );
		gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, accumTarget, 0 );
		// threejs的这里应该是默认 gl.COLOR_ATTACHMENT0, 所以还是只能用原生来写，不然不知道该改什么
		// 不过 这样的话，这里是原生的纹理对象，而three不知道怎么处理的，
		// 还真不能直接用原生的， 除非我能知道当前这个材质已经使用了多少个纹理，这样不会使得原本要用的纹理丢失
		gl.bindTexture( gl.TEXTURE_2D, accumAlphaTarget );
		gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, false );
		gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
		gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
		gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE );
		gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE );
		// webgl2 指定纹理存储级别    target    levels internalformat   widit         height
		gl.texStorage2D( gl.TEXTURE_2D, 1, gl.R16F, gl.drawingBufferWidth, gl.drawingBufferHeight );
		// webgl2 可用 COLOR_ATTACHMENT1
		gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, accumAlphaTarget, 0 );

		var depthTarget = gl.createTexture(); // 2 和深度缓冲区绑定
		gl.bindTexture( gl.TEXTURE_2D, depthTarget );
		gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, false );
		gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
		gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
		gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE );
		gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE );
		gl.texStorage2D( gl.TEXTURE_2D, 1, gl.DEPTH_COMPONENT16, gl.drawingBufferWidth, gl.drawingBufferHeight );
		//帧缓冲区的深度缓冲区
		//                        target         attachment           textarget      texture    level
		gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthTarget, 0 );

		// 将颜色写入第一和第二个 帧缓冲区,这个正对应着色器中的 out 输出 这个方法应是关联输出和attachment
		// The number of output locations available to a shader is limited. For fragment shaders, the limit is the advertised number of draw buffer
		// 输出变量的数量限制，对于片元着色器来说就是 已经声明了的 绘制 缓冲区（drawbuffer）

		gl.drawBuffers( [
			gl.COLOR_ATTACHMENT0,
			gl.COLOR_ATTACHMENT1
		] );
		// 绑定了帧缓冲区，初始化了三个纹理作为渲染目标

		gl.bindFramebuffer( gl.FRAMEBUFFER, null );


		gl.activeTexture( gl.TEXTURE0 );
		gl.bindTexture( gl.TEXTURE_2D, accumTarget );

		gl.activeTexture( gl.TEXTURE1 );
		gl.bindTexture( gl.TEXTURE_2D, accumAlphaTarget );

		this.quad.material.uniforms.accumAlpha.value = textures[ 1 ];
		this.quad.material.uniforms.tDiffuse.value = textures[ 0 ];
		// gl.useProgram(drawProgram);
		// gl.uniform1i(accumLocation, 1);
		// gl.uniform1i(accumAlphaLocation, 2);

		*/

	}

	render() {
		// 目前的逻辑，因为最终只绘制了使用了物理材质的着色器输出的颜色，所以其他物体自然不可见。
		// 这要怎么应用呢
		this.renderer.setRenderTarget( this.renderTargets );
		this.renderer.render( this.scene, this.camera );

		// 合成
		// gl.bindFramebuffer( gl.FRAMEBUFFER, null );
		this.renderer.setRenderTarget( null );
		this.quad.render( this.renderer );

	}


}

export { WeightedBlend };
